Skip to main content
Skip to main content

Architecture

web3agent is built around a single core idea: every blockchain capability should be accessible in two ways. AI agents running inside tools like Claude Code or Cursor reach it through the MCP protocol. Downstream TypeScript projects reach it by importing from the npm package directly. Both paths share the same underlying runtime, the same validation logic, and the same error handling.

This is the two-layer architecture.


The Two Layers

MCP Tool Layer

The MCP Tool Layer lives in src/tools/. It exposes blockchain capabilities as named tools that any MCP-compatible AI agent can discover and call. Tools are grouped by domain and registered in src/tools/<group>/index.ts.

When an AI agent connects to web3agent via npx web3agent, it gets a stdio MCP server. The agent can list all available tools, read their descriptions and input schemas, and invoke them by name with JSON arguments. The server validates inputs, executes the operation, and returns a structured result.

Programmatic SDK Layer

The SDK Layer lives in src/api/ and is exported from src/index.ts. It's for TypeScript projects that want to call web3agent functions directly, without running an MCP server.

SDK functions are thin wrappers. Each one calls getRuntime() to get a shared runtime instance, then calls invokeAndRequireData() to run the underlying tool and extract the typed result. If the tool returns an error, invokeAndRequireData() throws a Web3AgentError. If it succeeds, you get back a fully typed response.

// SDK usage — import and call directly
import { getSwapQuote } from "web3agent";

const quote = await getSwapQuote({
  fromToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
  toToken: "0x4200000000000000000000000000000000000006",   // WETH on Base
  fromAmount: "100000000", // 100 USDC (6 decimals)
  chainId: 8453,
});

Data Flow

MCP Tool Call

SDK Call


Source Structure

web3agent/src/
├── index.ts                    # Root public API exports (590+ lines)
├── cli.ts                      # CLI entry (init, policy, server commands)
│
├── runtime/                    # MCP Runtime Layer
│   ├── managed-runtime.ts      # Core runtime: tool registry, invocation, health
│   ├── server.ts               # MCP protocol server (stdio transport)
│   ├── startup.ts              # Server startup + graceful shutdown
│   └── default.ts              # Default runtime singleton
│
├── api/                        # SDK Layer (programmatic API)
│   ├── shared.ts               # getRuntime(), invokeAndRequireData(), createSDKInvoker()
│   ├── types.ts                # All SDK input/output types
│   ├── errors.ts               # Web3AgentError class
│   ├── swaps.ts                # getSwapQuote, executeSameChainSwap, getSwapHistory
│   ├── intents.ts              # prepareSwapIntent, prepareOrderIntent, prepareBridgeIntent
│   ├── orders.ts               # listOrders, placeOrder, cancelOrder
│   ├── explorer.ts             # 40+ blockchain data functions
│   ├── market.ts               # 20+ market data functions
│   ├── research.ts             # 10+ research functions
│   └── ...                     # acp, agdp, erc8004, x402, policy, simulation
│
├── tools/                      # MCP Tool Layer
│   ├── register.ts             # ToolDefinition interface + tool definitions
│   ├── orbs/                   # 15+ tools: quotes, swaps, orders, intents, TWAP, Spot
│   ├── lifi/                   # 3 tools: bridge quotes, execution, intents
│   ├── explorer/               # 40+ tools: accounts, transactions, tokens, contracts
│   ├── evm/                    # 30+ tools: contract interaction, transfers, ENS, gas
│   ├── market/                 # 20+ tools: TVL, prices, volumes, sentiment
│   ├── research/               # 10+ tools: security, yields, holders, governance
│   └── ...                     # wallet, tokens, operations, agdp, acp, erc8004, x402
│
├── chains/registry.ts          # Viem chain registry (17 chains)
├── wallet/                     # Wallet management (persistence, confirmation, audit)
├── config/env.ts               # Environment variable parsing
├── tokens/                     # Token resolver + registry + pricing
├── orbs/                       # Orbs integration (Liquidity Hub, TWAP, Spot)
├── lifi/                       # LI.FI bridge integration
├── evm/                        # EVM provider (viem)
└── policy/                     # Treasury policy engine + spend tracking

Package Entry Points

web3agent ships multiple entry points so you only import what you need.

Entry PointImport PathWhat You Get
Root SDK"web3agent"All SDK functions, types, schemas, config helpers
Runtime"web3agent/runtime"createRuntime(), Web3AgentRuntime type
MCP Server"web3agent/mcp"ProxyServer, startServer()
aGDP"web3agent/agdp"aGDP marketplace API client
X-402"web3agent/x402"X-402 payment protocol client

Most downstream projects only need "web3agent" for SDK functions or "web3agent/runtime" when they want direct tool invocation with a custom runtime configuration.


Supported Chains

web3agent supports 17 EVM chains out of the box. The default is Base (8453). Override it with the CHAIN_ID environment variable or pass chainId per call.

ChainID
Ethereum1
Base8453
Arbitrum42161
Optimism10
Polygon137
Linea59144
BSC56
Avalanche43114
zkSync Era324
Scroll534352
Mode34443
Blast81457
Mantle5000
Celo42220
Gnosis100
Sepolia11155111
Base Sepolia84532

Key Integrations

The tool layer aggregates multiple blockchain protocols behind a single namespace.

IntegrationTool PrefixCapabilities
Orbsorbs_Liquidity Hub swaps, dTWAP, dLIMIT, Spot orders
LI.FIlifi_Cross-chain bridges and swaps (20+ chains)
GOAT SDKvariesUniswap, Balancer, ERC-20/721, ENS, DexScreener, 0x, CoinGecko
Blockscoutblockscout_Indexed blockchain data (addresses, txs, NFTs, ABIs)
EVMevm_Live on-chain state (balances, reads, writes, gas, ENS)
ACPacp_Agent Cooperation Protocol (Virtuals ACPRouter)
aGDPagdp_Agent marketplace (Virtuals Protocol)
ERC-8004erc8004_On-chain agent identity and reputation
X-402x402_HTTP-native stablecoin payments for agents

Design Principles

stdout is reserved. The MCP protocol communicates over stdio. All internal logging goes to process.stderr.write() with a [module-name] prefix. Nothing should ever write to stdout except MCP protocol messages.

Zod is the single source of truth. Every tool's input schema is defined in Zod, then converted to JSON Schema for MCP registration. The same Zod schema validates runtime inputs. All fields carry .describe() annotations so AI agents can understand what each parameter does.

ESM only. All imports use .js extensions. The package ships as ESM with TypeScript declaration files.

Catch unknown, always. Error handling follows catch (e: unknown) throughout. No bare catches, no @ts-ignore.